package com.tuniu.agents.tools.hotel.utils;

import com.tuniu.agents.tools.hotel.tool.NlowestPriceHotelList;
import com.tuniu.agents.tools.hotel.tool.PlowestPriceHotelList;
import com.tuniu.agents.util.ConversationUtil;
import com.tuniu.agents.util.JsonUtil;
import org.springframework.ai.chat.model.ToolContext;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Objects;
import java.util.function.Supplier;

/**
 * Utility class for hotel-related common operations
 */
public class HotelCommonUtil {

    private static final String format = "yyyy-MM-dd";

    /**
     * Gets default date if input date is null or invalid
     * 
     * @param inputDate Input date string
     * @param defaultSupplier Supplier for default date
     * @return Valid date or default date
     */
    public static String getDefaultDate(String inputDate, Supplier<String> defaultSupplier) {
        return StringUtils.hasText(inputDate) && isValidDate(inputDate) ? inputDate : defaultSupplier.get();
    }

    /**
     * Gets default city name from context if not provided
     * 
     * @param cityName City name
     * @param poiName POI name
     * @param toolContext Tool context
     * @return City name to use
     */
    public static String getDefaultCityName(String cityName, String poiName, ToolContext toolContext) {
        if (!StringUtils.hasText(cityName) && !StringUtils.hasText(poiName)) {
            return ConversationUtil.getDefaultCityName(toolContext);
        }
        return cityName;
    }

    /**
     * Checks if date is expired (in the past)
     * Empty values are not validated
     * 
     * @param date Date string to check
     * @return True if date is invalid or in the past
     */
    public static boolean checkDateExpire(String date) {
        if (!StringUtils.hasText(date)) {
            return false;
        }
        return !isValidDate(date) || LocalDate.parse(date).isBefore(LocalDate.now());
    }

    /**
     * Checks if date has valid format
     * 
     * @param date Date string to check
     * @return True if date has valid format
     */
    private static boolean isValidDate(String date) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        sdf.setLenient(false);
        try {
            sdf.parse(date);
            return true;
        } catch (Exception e) {
            // Parsing failed, indicating invalid date
            return false;
        }
    }

    /**
     * Builds POI hotel markdown content
     * 
     * @param message Hotel data message
     * @param resultBuilder Markdown builder
     */
    public static void buildPoiHotelMarkdown(String message, StringBuilder resultBuilder) {
        if (resultBuilder.isEmpty()) {
            resultBuilder.append("| Hotel Name | Room Type | Check-in Date | Check-out Date | Lowest Price | Meal Options | Cancellation Policy | Review Summary | Business District |\n");
            resultBuilder.append("|--------|--------|--------|--------|--------|--------|--------|--------|--------|\n");
        }
        NlowestPriceHotelList.Response response = JsonUtil.fromJson(message, NlowestPriceHotelList.Response.class);

        if (Objects.isNull(response) || CollectionUtils.isEmpty(response.data())) {
            return;
        }

        for (NlowestPriceHotelList.HotelDataAbbr hotelData : response.data()) {
            StringBuilder rowBuilder = new StringBuilder();
            rowBuilder.append("|").append(hotelData.chineseName())
                    .append("|").append(hotelData.roomName())
                    .append("|").append(hotelData.checkIn())
                    .append("|").append(hotelData.checkOut())
                    .append("|").append(hotelData.lowestPrice())
                    .append("|").append(hotelData.meal())
                    .append("|").append(hotelData.refund())
                    .append("|").append(hotelData.commentDigest())
                    .append("|").append(hotelData.business())
                    .append("|\n");
            resultBuilder.append(rowBuilder);
        }
    }

    /**
     * Builds package hotel markdown content
     * 
     * @param message Hotel package data message
     * @param resultBuilder Markdown builder
     */
    public static void buildPkgHotelMarkdwon(String message, StringBuilder resultBuilder) {
        if (resultBuilder.isEmpty()) {
            resultBuilder.append("| Hotel Name | Room Type | Package Name | Check-in Date | Check-out Date | Price | Star Rating | Review Score |\n");
            resultBuilder.append("|--------|--------|--------|--------|--------|--------|--------|--------\n");
        }

        PlowestPriceHotelList.Response response = JsonUtil.fromJson(message, PlowestPriceHotelList.Response.class);
        if (Objects.isNull(response) || Objects.isNull(response.data()) || CollectionUtils.isEmpty(response.data().rows())){
            return;
        }

        for (PlowestPriceHotelList.PackageRow packageRow:response.data().rows()){
            StringBuilder rowBuilder = new StringBuilder();
            rowBuilder.append("|").append(packageRow.hotelName())
                    .append("|").append(packageRow.roomName())
                    .append("|").append(packageRow.packageName())
                    .append("|").append(packageRow.checkIn())
                    .append("|").append(packageRow.checkOut())
                    .append("|").append(packageRow.packagePrice())
                    .append("|").append(packageRow.starName())
                    .append("|").append(packageRow.commentScore())
                    .append("|\n");
            resultBuilder.append(rowBuilder);
        }
    }
}
